/*
 * Copyright (c) 2005 by IJ Soft
 *
 * This software is private property owned by IJ Soft,
 * disclosure or use of the code without written aggrement
 * is forbiden to any party.
 *
 * Under no circunstance IJ Soft takes any responsability
 * of direct and indirect damage caused by this software,
 * including loss of productivity and/or money.
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;


#endregion

namespace PowerControl
{
    /// <summary>
    /// An static threadsafe allocator that creates the object on class loading by the framework.
    /// </summary>
    /// <remarks>The framework specifies that the static constructor is called in an isolated compartment so there is no posibility that multiple threads can access the static constructor.</remarks>
    public class StaticAllocator<T> : Allocator<T> where T : class
    {
        static StaticAllocator()
        {
            ConstructorInfo constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], new ParameterModifier[0]);
            if (constructor == null)
                throw new Exception("The object that you want to singleton doesnt have a private/protected constructor so the property cannot be enforced.");

            try
            {
                instance = constructor.Invoke(new object[0]) as T;
            }
            catch (Exception e)
            {
                throw new Exception("The StaticSingleton couldnt be constructed, check if the type T has a default constructor", e);
            }
        }

        private StaticAllocator()
        { }

        private static readonly T instance;

        /// <summary>
        /// The static allocator Instance property returns the instance created on class loading.
        /// </summary>
        /// <remarks>This means that the singleton is instantiated at the moment in which a class has a reference to that type even if it never calls the Instance method.</remarks>
        public override T Instance
        {
            get { return instance; }
        }

        public override void Dispose()
        { }
    }
}
